﻿using Microsoft.AspNetCore.DataProtection.KeyManagement;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace XinLife.Core.Helper
{
    public class SecurityUtils
    {
        private static string Encrypt(HashAlgorithm hashAlgorithm, string dataToHash)
        {
            byte[] hashBytes = hashAlgorithm.ComputeHash(Encoding.UTF8.GetBytes(dataToHash));

            return string.Join("", hashBytes.Select(i => i.ToString("x2")));
        }

        public static string EncryptMD5(string dataToHash)
        {
            return Encrypt(new MD5CryptoServiceProvider(), dataToHash);
        }

        public static string EncryptSHA1(string dataToHash)
        {
            return Encrypt(new SHA1CryptoServiceProvider(), dataToHash);
        }

        public static string EncryptSHA256(string dataToHash)
        {
            return Encrypt(new SHA256CryptoServiceProvider(), dataToHash);
        }

        public static string EncryptSHA512(string dataToHash)
        {
            return Encrypt(new SHA512CryptoServiceProvider(), dataToHash);
        }
        public static string EncryptHmacSHA256(string dataToHash, string secret)
        {
            byte[] keyByte = Encoding.UTF8.GetBytes(secret);
            return Encrypt(new HMACSHA256(keyByte), dataToHash);
        }
        public static string EncryptHMACMD5(string dataToHash, string secret)
        {
            byte[] keyByte = Encoding.UTF8.GetBytes(secret);
            return Encrypt(new HMACMD5(keyByte), dataToHash);
        }


        public static bool IsHashMatch(HashAlgorithm hashAlgorithm, string hashedText, string unhashedText)
        {
            string hashedTextToCompare = Encrypt(hashAlgorithm, unhashedText);
            return (String.Compare(hashedText, hashedTextToCompare, false) == 0);
        }

        public static string GenerateAesKey()
        {
            using (Aes aes = Aes.Create())
            {
                aes.KeySize = 128;
                aes.GenerateKey();
                return Convert.ToBase64String(aes.Key);
            }
        }

        public static string AesEncrypt(string message, string key)
        {
            byte[] keyBytes = Convert.FromBase64String(key);
            byte[] messageBytes = Encoding.UTF8.GetBytes(message);

            using (Aes aes = Aes.Create())
            {
                aes.Key = keyBytes;
                aes.GenerateIV();

                ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
                byte[] encryptedMessage = encryptor.TransformFinalBlock(messageBytes, 0, messageBytes.Length);

                //新建iv + 加密的数据字节的长度 的字节
                byte[] result = new byte[aes.IV.Length + encryptedMessage.Length];
                //iv复制到结果中
                Buffer.BlockCopy(aes.IV, 0, result, 0, aes.IV.Length);
                //加密的数据复制到结果中
                Buffer.BlockCopy(encryptedMessage, 0, result, aes.IV.Length, encryptedMessage.Length);

                return Convert.ToBase64String(result);
            }
        }
        public static string AesDecrypt(string encryptedMessage, string key)
        {
            byte[] keyBytes = Convert.FromBase64String(key);
            byte[] encryptedBytes = Convert.FromBase64String(encryptedMessage);

            using (Aes aes = Aes.Create())
            {
                aes.Key = keyBytes;

                byte[] iv = new byte[aes.IV.Length];
                Buffer.BlockCopy(encryptedBytes, 0, iv, 0, aes.IV.Length);

                byte[] message = new byte[encryptedBytes.Length - aes.IV.Length];
                Buffer.BlockCopy(encryptedBytes, aes.IV.Length, message, 0, message.Length);

                ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, iv);
                byte[] decryptedMessage = decryptor.TransformFinalBlock(message, 0, message.Length);

                return Encoding.UTF8.GetString(decryptedMessage);
            }
        }


        /// <summary>
        /// 生成rsa公钥和私钥 
        /// </summary>
        /// <returns></returns>
        public static (string, string) GenerateRSAPublicKeyAndPrivateKey()
        {
            RsaKeyPairGenerator generator = new RsaKeyPairGenerator();
            generator.Init(new KeyGenerationParameters(new SecureRandom(), 1024));

            AsymmetricCipherKeyPair keyPair = generator.GenerateKeyPair();
            RsaKeyParameters publicKey = (RsaKeyParameters)keyPair.Public;
            RsaKeyParameters privateKey = (RsaKeyParameters)keyPair.Private;
            // 将私钥转换为 SubjectPublicKeyInfo 对象
            byte[] publicKeyBytes = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey).GetEncoded();
            string publicKeyString = Convert.ToBase64String(publicKeyBytes);
            // 将私钥转换为 PrivateKeyInfo 对象
            var privateKeyBytes = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKey).GetEncoded();
            string privateKeyString = Convert.ToBase64String(privateKeyBytes);
            return (publicKeyString, privateKeyString);
        }
        /// <summary>
        /// RSA分块加密
        /// </summary>
        public static string RSAEncrypt(string plainText, string publicKey)
        {
            // 解析公钥字符串
            var rsaKeyParameters = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey));
            // 初始化RSA加密器
            IBufferedCipher cipher = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding");
            cipher.Init(true, rsaKeyParameters);
            // 分块加密
            byte[] inputBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
            int blockSize = rsaKeyParameters.Modulus.BitLength / 8 - 11; // 根据公钥长度计算分块大小
            int inputLength = inputBytes.Length;
            int offset = 0;
            using (MemoryStream outputStream = new MemoryStream())
            {
                while (inputLength - offset > 0)
                {
                    int length = Math.Min(blockSize, inputLength - offset);
                    byte[] block = new byte[length];
                    Buffer.BlockCopy(inputBytes, offset, block, 0, length);

                    byte[] outputBytes = cipher.DoFinal(block);
                    outputStream.Write(outputBytes, 0, outputBytes.Length);

                    offset += blockSize;
                }
                return Convert.ToBase64String(outputStream.ToArray());
            }
        }
        /// <summary>
        /// RSA分块解密
        /// </summary>
        public static string RSADecrypt(string cipherText, string privateKey)
        {
            // 解析私钥字符串
            var rsaPrivateKeyParameters = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKey));
            // 初始化RSA解密器
            IBufferedCipher cipher = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding");
            cipher.Init(false, rsaPrivateKeyParameters);
            // 分块解密
            byte[] inputBytes = Convert.FromBase64String(cipherText);
            int blockSize = rsaPrivateKeyParameters.Modulus.BitLength / 8; // 根据私钥长度计算分块大小
            int inputLength = inputBytes.Length;
            int offset = 0;
            using (MemoryStream outputStream = new MemoryStream())
            {
                while (inputLength - offset > 0)
                {
                    int length = Math.Min(blockSize, inputLength - offset);
                    byte[] block = new byte[length];
                    Buffer.BlockCopy(inputBytes, offset, block, 0, length);

                    byte[] outputBytes = cipher.DoFinal(block);
                    outputStream.Write(outputBytes, 0, outputBytes.Length);

                    offset += blockSize;
                }
                return System.Text.Encoding.UTF8.GetString(outputStream.ToArray());
            }
        }

    }
}
